-- vim: set autoindent noexpandtab tabstop=4 shiftwidth=4 softtabstop=-1:
--[[
	Copyright (c) 2018 James Dornan <james@catch22.com>

    This file is part of dbtable.

    dbtable is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    dbtable is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with dbtable.  If not, see <https://www.gnu.org/licenses/>.
--]]

--- dbtable
-- Allows access to a database table as a Lua table. All data is compressed and
-- encoded when used in the context of a minetest mod.
--
-- @module dbtable
-- @author James Dornan <james@catch22.com>
-- @copyright James Dornan <james@catch22.com> 2018
-- @release 1.0

---@usage
local usage = [[
local tbl = require("dbtable").new({
    db   = "sqlite3",
    name = "test",
    file = "/tmp/test.sqlite3"
})

tbl[1] = 'b'
tbl[2] = 'c'
tbl[3] = 'e'

The above example would create a sqlite3 database, and then create within it
a table called "test" with 2 columns, key and value. Key it set as a primary
key in the database, and must be unique.

This would be the result.

$sqlite3 /tmp/test.sqlite3
sqlite> .schema
CREATE TABLE test
            (
                key   VARCHAR(54) PRIMARY KEY,
                value VARCHAR(512)
            );
sqlite> SELECT * FROM test;
1|b
2|c
3|e
sqlite>
]]

local dbtable = {}

--- Constructor function for sqlite3table module
--  See: <a href=https://keplerproject.github.io/luasql/>luasql</a>,
--  <a href=https://forum.minetest.net/viewtopic.php?t=12471/>Trusted mods</a>,
--  <a href=http://lua-users.org/wiki/MetatableEvents/>Metatable Events</a>
--
-- @param opts table of confuration options
-- @return Table object that has all the metamethods for acting as a Lua table [table]
function dbtable.new(opts)
	assert(type(opts)      == "table")
	assert(type(opts.db)   == "string")
	assert(type(opts.name) == "string")

	if (opts.db == "postgresql") then
		assert(type(opts.connection) == "string")
	else
		assert(opts.db == "sqlite3")
		assert(type(opts.file) == "string")
	end

	--- int: Maximum value size
	local keySize   = 64
	--- int: Maximum value size
	local valueSize   = 8192
	--- int: Minimum bytes before compression
	local minCompress = 50

	-- Currently I'm using dbtable with Minetest often
	if minetest then
		opts.serialize   = minetest.serialize
		opts.deserialize = minetest.deserialize
		opts.compress    = minetest.compress
		opts.decompress  = minetest.decompress
	end

	if opts.keysize == nil then
	  opts.keysize = keySize
	end

	if opts.valuesize == nil then
	  opts.valuesize = valueSize
	end

	return assert(require("dbtable." .. opts.db).new(opts))
end

return dbtable
